package hud;

import com.google.gson.Gson;
import data.DatabaseClient;
import data.DatabaseClientCollect;
import data.ServerInformationList;
import data.ServerShortInfomation;
import event.EventBase;
import event.EventEnum;
import event.EventSystem;
import event.ListenerInterface;
import file.ServerListFile;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.util.Pair;
import network.ConnectionFactory;
import network.DirectConnection;
import network.DirectConnectionConfig;

import java.util.Optional;

public class ServerListDialog extends Dialog<Pair<String, String>> implements ListenerInterface {
    private static ServerListDialog instance;
    private TableView tableView;
    private ServerListDialog() {

    }

    public static ServerListDialog instance() {
        if (instance == null) {
            instance = new ServerListDialog();
            instance.construct();
        }
        return instance;
    }

    private Dialog construct() {
        Dialog<Pair<String, String>> dialog = instance;
        dialog.setTitle("Server List");

        ButtonType connectButtonType = new ButtonType("Connect", ButtonBar.ButtonData.OK_DONE);
        ButtonType cancelButtonType = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
        dialog.getDialogPane().getButtonTypes().addAll(connectButtonType, cancelButtonType);
        Button connectButton = (Button) dialog.getDialogPane().lookupButton(connectButtonType);
        connectButton.setDisable(true);
        connectButton.setOnAction(event -> {
            doConnect();
        });

        dialog.getDialogPane().setMaxWidth(600);

        //1、由VBox组织的两段
        VBox vBox = new VBox();

        //1.1
        HBox hBox = new HBox();
        hBox.setPadding(new Insets(0, 0, 5, 0));
        Hyperlink link = new Hyperlink("Create");
        link.setOnAction(event -> {
            showConnectionConfig();
        });
        hBox.getChildren().add(link);
        Label label = new Label(",");
        hBox.getChildren().add(label);

        link = new Hyperlink("Edit");
        link.setOnAction(event -> {
        });
        hBox.getChildren().add(link);
        label = new Label(",");
        hBox.getChildren().add(label);
        link = new Hyperlink("Remove");
        link.setOnAction(event -> {
            // remove from tableView
            Object selectedItem = tableView.getSelectionModel().getSelectedItem();
            tableView.getItems().remove(selectedItem);

            // rewrite server list file
            ObservableList<ServerShortInfomation> rows = tableView.getItems();
            ServerInformationList serverInformationList = new ServerInformationList();
            for (int i = 0; i < rows.size(); ++i) {
                serverInformationList.addServerShortInformation(rows.get(i));
            }
            ServerListFile.instance().save(new Gson().toJson(serverInformationList));
        });
        hBox.getChildren().add(link);
        label = new Label(",");
        hBox.getChildren().add(label);
        link = new Hyperlink("Clone");
        link.setOnAction(event -> {
        });
        hBox.getChildren().add(link);

        vBox.getChildren().add(hBox);

        //1.2 Table
        tableView = new TableView();
        TableColumn nameCol = new TableColumn("Name");
        nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
        nameCol.setPrefWidth(200);
        TableColumn addressCol = new TableColumn("Address / HostName");
        addressCol.setCellValueFactory(new PropertyValueFactory<>("host"));
        addressCol.setPrefWidth(200);
        TableColumn attributesCol = new TableColumn("Attributes");
        attributesCol.setCellValueFactory(new PropertyValueFactory<>("attributes"));
        attributesCol.setPrefWidth(200);
        TableColumn authCol = new TableColumn("Auth.Database / User");
        authCol.setCellValueFactory(new PropertyValueFactory<>("auth"));
        authCol.setPrefWidth(200);

        tableView.getColumns().addAll(nameCol, addressCol, attributesCol, authCol);
        tableView.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> {
            if (newSelection != null) {
                connectButton.setDisable(false);
            }
            else {
                Object item = tableView.getSelectionModel().getSelectedItem();
                if (item == null) {
                    connectButton.setDisable(true);
                }
                else {
                    connectButton.setDisable(false);
                }
            }
        });
        tableView.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if (event.getClickCount() == 2) {
                    doConnect();
                    instance.close();
                }
            }
        });
        String content = ServerListFile.instance().read();
        if (!content.isEmpty()) {
            ServerInformationList serverInformationList = new Gson().fromJson(content, ServerInformationList.class);
            for (int i = 0; i < serverInformationList.size(); ++i) {
                tableView.getItems().add(serverInformationList.get(i));
            }
        }
        vBox.getChildren().add(tableView);

        dialog.getDialogPane().setContent(vBox);

        EventSystem.instance().on(EventEnum.serverListFileRefresh, this);
        return dialog;
    }

    public TableView getTableView() {
        return tableView;
    }

    private void showConnectionConfig() {
        Dialog<Pair<String, String>> dialog = new Dialog<>();
        dialog.setTitle("Connection Settings");
        dialog.getDialogPane().setBackground(new Background(new BackgroundFill(Color.rgb(240, 240, 240), null, null)));
        dialog.getDialogPane().setPadding(new Insets(10, 10, 0, 10));
        dialog.getDialogPane().setMaxWidth(610);

        ButtonType saveButtonType = new ButtonType("Save", ButtonBar.ButtonData.OK_DONE);
        ButtonType cancelButtonType = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
        ButtonType testButtonType = new ButtonType("Test", ButtonBar.ButtonData.LEFT);

        dialog.getDialogPane().getButtonTypes().addAll(saveButtonType, cancelButtonType, testButtonType);
        final Button buttonTest = (Button) dialog.getDialogPane().lookupButton(testButtonType);
        Image image = new Image("info.png");
        ImageView imageView = new ImageView(image);
        buttonTest.setGraphic(imageView);
        buttonTest.addEventFilter(
                ActionEvent.ACTION,
                event -> {
                    event.consume();
                }
        );

        dialog.getDialogPane().setMinWidth(500);

        //1. 5个tab
        TabPane tabPane = new TabPane();
        tabPane.setBackground(new Background(new BackgroundFill(Color.rgb(255, 255, 255), null, null)));
        tabPane.getStyleClass().add("floating");

        //1.1 tab1
        Tab tab = ConnectionTab.Instance().construct();
        tabPane.getTabs().add(tab);

        //1.2 tab2
        tab = AuthenticationTab.Instance().construct();
        tabPane.getTabs().add(tab);

        //1.3 tab3
        tab = SshTab.Instance().Construct();
        tabPane.getTabs().add(tab);

        //1.4 tab4
        tab = SslTab.Instance().construct();
        tabPane.getTabs().add(tab);

        //1.5 tab5
        tab = AdvancedTab.Instance().construct();
        tabPane.getTabs().add(tab);

        // save button process
        final Button buttonSave = (Button) dialog.getDialogPane().lookupButton(saveButtonType);
        buttonSave.addEventFilter(
                ActionEvent.ACTION,
                event -> {
                    String name = ConnectionTab.Instance().getName();
                    String host = ConnectionTab.Instance().getHost();
                    String port = ConnectionTab.Instance().getPort();

                    // 原来的列表从文件中读出来
                    String content = ServerListFile.instance().read();
                    ServerInformationList serverInformationList;
                    if (content.isEmpty()) {
                        serverInformationList = new ServerInformationList();
                    }
                    else {
                        serverInformationList = new Gson().fromJson(content, ServerInformationList.class);
                    }

                    // 增加新的
                    ServerShortInfomation serverShortInfomation = new ServerShortInfomation();
                    serverShortInfomation.setAuth("");
                    serverShortInfomation.setAttributes("");
                    serverShortInfomation.setName(name);
                    serverShortInfomation.setHost(host);
                    serverShortInfomation.setPort(port);
                    serverInformationList.addServerShortInformation(serverShortInfomation);

                    Gson gson = new Gson();
                    ServerListFile.instance().save(gson.toJson(serverInformationList));
                    event.consume();
                }
        );

        dialog.getDialogPane().setContent(tabPane);

        Optional<Pair<String, String>> result = dialog.showAndWait();
    }

    @Override
    public void process(EventBase event) {
        if (event.getName().equals(EventEnum.serverListFileRefresh)) {
            try {
                String result = ServerListFile.instance().read();

                if (result.isEmpty()) return;

                tableView.getItems().clear();

                Gson gson = new Gson();
                ServerInformationList serverInformationList = gson.fromJson(result, ServerInformationList.class);

                for (int i = 0; i < serverInformationList.size(); ++i) {
                    tableView.getItems().add(serverInformationList.get(i));
                }
            }
            catch (Exception e) {
                System.out.println(e.toString());
            }
        }
    }

    private void doConnect() {
        DirectConnection directConnection = (DirectConnection) ConnectionFactory.instance().create(DirectConnection.class);
        DirectConnectionConfig config = new DirectConnectionConfig();
        ServerShortInfomation selectedItem = (ServerShortInfomation)tableView.getSelectionModel().getSelectedItem();
        config.setHost(selectedItem.getHost());
        config.setPort(Integer.parseInt(selectedItem.getPort()));
        config.setDatabaseName(selectedItem.getName());
        directConnection.init(config);
        DatabaseClient databaseClient = directConnection.connect();
        if (databaseClient != null) {
            DatabaseClientCollect.instance().add(databaseClient);
        }
    }
}
